package com.itheima.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.common.exception.NcException;
import com.itheima.common.exception.enums.ResponseEnum;
import com.itheima.common.threadlocal.UserHolder;
import com.itheima.common.util.BeanHelper;
import com.itheima.common.util.DateTimeUtil;
import com.itheima.common.util.StringUtil;
import com.itheima.common.vo.PageResult;
import com.itheima.sys.dto.*;
import com.itheima.sys.entity.Company;
import com.itheima.sys.entity.CompanyUser;
import com.itheima.sys.entity.Department;
import com.itheima.sys.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrganizationService {


    @Autowired
    private ICompanyService companyService;

    @Autowired
    private IDepartmentService departmentService;

    @Autowired
    private ICompanyUserService companyUserService;

    @Autowired
    private ISysUserService sysUserService;

    /**
     * 查询部门树形数据
     *
     * @return
     */
    public List<DepartmentDTO> queryDeparentTree() {

        List<DepartmentDTO> departmentDTOS = new ArrayList<>();

        //1.根节点 根据当前用户登录企业ID 查询当前企业信息  封装DepartmentDTO对象 isCompnay=true
        Long companyId = UserHolder.getCompanyId();
        Company company = companyService.getById(companyId);
        if (company == null) {
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }
        //1.1 将企业数据当成属性数据 定义节点
        DepartmentDTO companyDepartment = BeanHelper.copyProperties(company, DepartmentDTO.class);
        //2.查询企业下包含顶级部门  parent_id=0
        QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();
        departmentQueryWrapper.lambda().eq(Department::getCompanyId, companyId);
        departmentQueryWrapper.lambda().eq(Department::getParentId, 0);
        List<Department> topDeparments = departmentService.list(departmentQueryWrapper);
        if (!CollectionUtils.isEmpty(topDeparments)) {
            List<DepartmentDTO> topDeparmentDTOS = BeanHelper.copyWithCollection(topDeparments, DepartmentDTO.class);
            companyDepartment.setChildren(topDeparmentDTOS);
            //3.递归查询部门是否包含子节点
            this.queryChildDepartment(topDeparmentDTOS);
        }
        List<DepartmentDTO> companyDepts = new ArrayList<>();
        companyDepts.add(companyDepartment);
        return companyDepts;
    }


    /**
     * 查询传入部门集合 是否包含子部门
     *
     * @param topDeparmentDTOS
     */
    private void queryChildDepartment(List<DepartmentDTO> topDeparmentDTOS) {
        for (DepartmentDTO topDeparmentDTO : topDeparmentDTOS) {
            QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Department::getParentId, topDeparmentDTO.getId());
            List<Department> childrenDepts = departmentService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(childrenDepts)) {
                List<DepartmentDTO> departmentDTOS = BeanHelper.copyWithCollection(childrenDepts, DepartmentDTO.class);
                topDeparmentDTO.setChildren(departmentDTOS);
                this.queryChildDepartment(departmentDTOS);
            }
        }
    }

    /**
     * 展示企业员工分页
     *
     * @param page
     * @param pageSize
     * @param departmentId
     * @param keyword
     * @return
     */
    public PageResult<CompanyUserDTO> queryCompanyMembers(Integer page, Integer pageSize, Long departmentId, String keyword) {
        Long companyId = UserHolder.getCompanyId();
        //封装查询条件
        QueryWrapper<CompanyUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CompanyUser::getCompanyId, companyId);
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.lambda().like(CompanyUser::getUsername, keyword);
        }
        //1判断当前登录终端类型 PC端：默认提交departmentId=0 默认查询未关联部门员工数据
        if ("pc_client".equals(UserHolder.getUserInfo().getClientId())) {
            if (departmentId == 0) {
                //查询未关联到企业 where deparent_id is null
                queryWrapper.lambda().isNull(CompanyUser::getDepartmentId);
            } else {
                queryWrapper.lambda().eq(CompanyUser::getDepartmentId, departmentId);
            }
        } else {
            //移动端
            queryWrapper.lambda().eq(CompanyUser::getDepartmentId, departmentId);
        }
        //2.执行查询
        IPage<CompanyUser> ipage = new Page<>(page, pageSize);
        ipage = companyUserService.page(ipage, queryWrapper);
        List<CompanyUser> companyUserList = ipage.getRecords();
        if (!CollectionUtils.isEmpty(companyUserList)) {
            List<CompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(companyUserList, CompanyUserDTO.class);
            return new PageResult<>(ipage.getTotal(), ipage.getPages(), companyUserDTOS);
        }
        return null;
    }

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Transactional
    public void excelImport(MemberExcelRequest memberExcelChineseDTOs) {
        Long companyId = UserHolder.getCompanyId();
        if (memberExcelChineseDTOs != null && memberExcelChineseDTOs.getXlsxJson() != null && memberExcelChineseDTOs.getXlsxJson().length > 0) {
            List<MemberExcelDTO> memberExcelList = Arrays.stream(memberExcelChineseDTOs.getXlsxJson()).map(memberExcelChinese -> {
                MemberExcelDTO memberExcel = new MemberExcelDTO();
                memberExcel.setAddress(memberExcelChinese.get办公地点());
                memberExcel.setDepartmentName(memberExcelChinese.get部门());
                memberExcel.setEmail(memberExcelChinese.get邮箱());
                memberExcel.setEnable(memberExcelChinese.get激活状态());
                memberExcel.setIfManager(memberExcelChinese.get是否部门主管());
                memberExcel.setMobile(memberExcelChinese.get手机号());
                memberExcel.setPost(memberExcelChinese.get职位());
                memberExcel.setRemark(memberExcelChinese.get备注());
                memberExcel.setRoleDesc(memberExcelChinese.get角色());
                memberExcel.setTimeEntry(memberExcelChinese.get入职时间());
                memberExcel.setWorkNumber(memberExcelChinese.get工号());
                memberExcel.setUsername(memberExcelChinese.get姓名());
                return memberExcel;
            }).collect(Collectors.toList());
            List<CompanyUser> companyUsers = new ArrayList<>();
            for (MemberExcelDTO memberExcel : memberExcelList) {
                //判断用户手机号是否重复  邮箱  工号
                Boolean flag = sysUserService.checkExists(memberExcel.getMobile());
                if (flag) {
                    continue;
                }
                SysUser sysUser = BeanHelper.copyProperties(memberExcel, SysUser.class);
                sysUser.setPassword(passwordEncoder.encode("123456"));
                sysUser.setLastLoginCompanyId(companyId);
                //新增系统用户
                boolean save = sysUserService.save(sysUser);
                if(!save){
                    continue;
                }
                CompanyUser companyUser = new CompanyUser();
                companyUser.setUserId(sysUser.getId());
                companyUser.setTimeEntry(DateTimeUtil.strToDate(memberExcel.getTimeEntry(), "yyyy-MM-dd"));
                companyUser.setCompanyId(companyId);
                companyUser.setCompanyName(UserHolder.getUserInfo().getCompanyName());
                companyUser.setPost(memberExcel.getPost());
                companyUser.setMobile(memberExcel.getMobile());
                companyUser.setWorkNumber(memberExcel.getWorkNumber());
                companyUser.setRemark(memberExcel.getRemark());
                companyUser.setEmail(memberExcel.getEmail());
                companyUser.setOfficeAddress(memberExcel.getAddress());
                companyUser.setUsername(memberExcel.getUsername());
                companyUser.setCreateTime(new Date());
                companyUser.setEnable(memberExcel.getEnable().equals("可用") ? true : false);
                companyUsers.add(companyUser);
            }

            companyUserService.saveBatch(companyUsers);
        } else {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
    }

    /**
     * 解析Excel文件，将企业员工初始化到数据库
     * @param file
     */
    @Transactional
    public void parseExcel(MultipartFile file) throws Exception {
        //读取文件流，创建excel工作簿对象
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取标签页
        Sheet sheet = workbook.getSheetAt(0);

        //遍历标签页获取行对象
        List<MemberExcelDTO> memberExcelDTOList = new ArrayList<>();
        for (Row row : sheet) {
            //忽略第一行表头
            if(row.getRowNum()==0){
                continue;
            }
            String userName = getCellValue(row.getCell(0));
            String mobile = getCellValue(row.getCell(1));
            String departmentName = getCellValue(row.getCell(2));
            String post = getCellValue(row.getCell(3));
            String workNum = getCellValue(row.getCell(4));
            String ifManager = getCellValue(row.getCell(5));
            String email = getCellValue(row.getCell(6));
            String address = getCellValue(row.getCell(7));
            String remark = getCellValue(row.getCell(8));
            String hireDate = getCellValue(row.getCell(9));
            String enable = getCellValue(row.getCell(10));
            String roleDesc = getCellValue(row.getCell(11));

            MemberExcelDTO memberExcel = new MemberExcelDTO();
            memberExcel.setAddress(address);
            memberExcel.setDepartmentName(departmentName);
            memberExcel.setEmail(email);
            memberExcel.setEnable(enable);
            memberExcel.setIfManager(ifManager);
            memberExcel.setMobile(mobile);
            memberExcel.setPost(post);
            memberExcel.setRemark(remark);
            memberExcel.setRoleDesc(roleDesc);
            memberExcel.setTimeEntry(hireDate);
            memberExcel.setWorkNumber(workNum);
            memberExcel.setUsername(userName);
            memberExcelDTOList.add(memberExcel);
        }
        this.handlerMemberExcelDTO(memberExcelDTOList);
    }


    //用于格式化十进制数字-#阿拉伯数字如果不存在就显示为空
    private static final DecimalFormat df = new DecimalFormat("#");


    /**
     * 获取单元格各类型值，返回字符串类型
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell){
        String value = null;
        switch (cell.getCellType()) {
            case STRING:
                value = cell.getRichStringCellValue().getString();
                break;
            case NUMERIC:
                if("General".equals(cell.getCellStyle().getDataFormatString())){
                    value = df.format(cell.getNumericCellValue());
                }else{
                    //日期类型
                    value = DateTimeUtil.dateToStr(cell.getDateCellValue(), "yyyy-MM-dd");
                }
                break;
            case BOOLEAN:
                value = String.valueOf(cell.getBooleanCellValue());
                break;
            case BLANK:
                value = "";
                break;
            default:
                value = cell.toString();
                break;
        }
        return value;
    }

    /**
     * 处理员工数据业务，将数据持久化到数据库
     * @param memberExcelList
     * @throws Exception
     */
    private void handlerMemberExcelDTO(List<MemberExcelDTO> memberExcelList) throws Exception {
        Long companyId = UserHolder.getCompanyId();
        String companyName = UserHolder.getUserInfo().getCompanyName();
        List<CompanyUser> companyUsers = new ArrayList<>();
        List<SysUser> sysUsers = new ArrayList<>();
        for (MemberExcelDTO memberExcel : memberExcelList) {
            //判断系统用户是否重复
            Boolean flag = sysUserService.checkExists(memberExcel.getMobile());
            if (flag) {
                continue;
            }
            SysUser sysUser = BeanHelper.copyProperties(memberExcel, SysUser.class);
            sysUser.setPassword(passwordEncoder.encode("123456"));
            sysUser.setLastLoginCompanyId(companyId);
            sysUsers.add(sysUser);
            boolean b = sysUserService.save(sysUser);
            if(!b){
                continue;
            }

            CompanyUser companyUser = new CompanyUser();
            companyUser.setUserId(sysUser.getId());
            companyUser.setTimeEntry(DateTimeUtil.strToDate(memberExcel.getTimeEntry(), "yyyy-MM-dd"));
            companyUser.setCompanyId(companyId);
            companyUser.setCompanyName(companyName);
            companyUser.setPost(memberExcel.getPost());
            companyUser.setMobile(memberExcel.getMobile());
            companyUser.setWorkNumber(memberExcel.getWorkNumber());
            companyUser.setRemark(memberExcel.getRemark());
            companyUser.setEmail(memberExcel.getEmail());
            companyUser.setOfficeAddress(memberExcel.getAddress());
            companyUser.setUsername(memberExcel.getUsername());
            companyUser.setCreateTime(new Date());
            companyUser.setEnable(memberExcel.getEnable().equals("可用") ? true : false);
            companyUsers.add(companyUser);
        }
        companyUserService.saveBatch(companyUsers);
    }

    public List<Long> queryDepartmentIds() {
        //查询当前企业顶级部门
        QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Department::getCompanyId, UserHolder.getCompanyId());
        queryWrapper.lambda().eq(Department::getParentId, 0);
        //指定查询某列
        queryWrapper.lambda().select(Department::getId);
        List<Long> collect = departmentService.list(queryWrapper).stream().map(Department::getId).collect(Collectors.toList());
        return collect;
    }

    /**
     * 查询当前企业部门，部门下包含员工
     * @param departmentId
     * @param includeMember
     * @return
     */
    public List<DepartmentOrUserSimpleDTO> querySimpleDepartment(Long departmentId, Integer includeMember) {
        Long companyId = UserHolder.getCompanyId();
        //1.根据部门ID查询下属部门列表
        QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Department::getCompanyId, companyId);
        if(departmentId!=null){
            queryWrapper.lambda().eq(Department::getParentId, departmentId);
        }
        List<Department> departmentList = departmentService.list(queryWrapper);
        List<DepartmentOrUserSimpleDTO> DepartmentSimpleDTOs = departmentList.stream().map(department -> {
            //将部门对象转为 DepartmentOrUserSimpleDTO
            DepartmentOrUserSimpleDTO departmentOrUserSimpleDTO = BeanHelper.copyProperties(department, DepartmentOrUserSimpleDTO.class);
            departmentOrUserSimpleDTO.setType(1);
            return departmentOrUserSimpleDTO;
        }).collect(Collectors.toList());

        List<DepartmentOrUserSimpleDTO> companyUserSimpleDTOs = null;
        //3.判断是否需要查询员工记录
        if(includeMember==0){
            QueryWrapper<CompanyUser> companyUserQueryWrapper = new QueryWrapper<>();
            companyUserQueryWrapper.lambda().eq(CompanyUser::getCompanyId, companyId);
            companyUserQueryWrapper.lambda().eq(CompanyUser::getDepartmentId, departmentId);
            List<CompanyUser> companyUserList = companyUserService.list(companyUserQueryWrapper);
            companyUserSimpleDTOs= companyUserList.stream().map(companyUser -> {
                DepartmentOrUserSimpleDTO departmentOrUserSimpleDTO = new DepartmentOrUserSimpleDTO();
                departmentOrUserSimpleDTO.setId(companyUser.getId());
                departmentOrUserSimpleDTO.setName(companyUser.getUsername());
                departmentOrUserSimpleDTO.setType(2);
                return departmentOrUserSimpleDTO;
            }).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(DepartmentSimpleDTOs)){
            return companyUserSimpleDTOs;
        }
        DepartmentSimpleDTOs.addAll(companyUserSimpleDTOs);
        return DepartmentSimpleDTOs;
    }
}
